﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text;
//using System.Threading; //不允许在 using 中出现 这个命名空间, 需要的话请将这个命名空间写在行内代码中

namespace InkFx.WinControl.Core
{
    /// <summary>
    /// 用于多线程编程的任务辅助类
    /// <para>2015年, 作者为了公司项目, 而手写了一个 ThreadQueue 类, 实现多线程协同工作完成一个集合的任务</para>
    /// <para>2018年, 作者在实际项目中, 尝试使用.Net 4.5 的 Task 编程, 其实用得不太理想</para>
    /// <para>又鉴于 项目最终的运行环境 需要尽量避免 .Net 4.5+</para>
    /// <para>于是, 作者模仿 .Net 4.5 的 Task 定义, 再结合了之前 ThreadQueue 的功能, 手动实现了如下的 Task多线程类</para>
    /// <para>本辅助类 没有使用线程池, 而是新开线程(线程数目反而可控), 也因此实现了 Cancel() 函数 用来随时结束任务(直接结束进程, 不需要引入额外的程序代码, 让编码只专注业务)</para>
    /// <para>而原生 Task 基于 CancellationTokenSource 实现 任务Cancel机制, 使用非常麻烦(且不一定能结束任务), 这个东西需要运行函数的配合, 需要修改多处代码, 谁用谁知道: CancellationTokenSource 就是个坑</para>
    /// <para>COPYRIGHT (C) InkFx http://www.ink-fx.com  License MIT</para>
    /// </summary>
    internal class Task : IDisposable
    {
        #region  静 态 函 数

        
        /// <summary>
        /// 开启一个线程, 使其休眠指定的 毫秒数
        /// </summary>
        /// <param name="delay">新开线程休眠的毫秒数</param>
        /// <returns></returns>
        public static Task Delay(int delay)
        {
            Task task = new Task(() => { System.Threading.Thread.Sleep(delay); });
            task.Start();
            return task;
        }
        /// <summary>
        /// 开启一个线程, 执行一个 Action
        /// </summary>
        /// <param name="action">执行体</param>
        /// <returns>任务对象</returns>
        public static Task Run(Action action)
        {
            Task task = new Task(action);
            task.Start();
            return task;
        }
        /// <summary>
        /// 开启一个线程, 执行一个 Function
        /// </summary>
        /// <param name="function">执行体</param>
        /// <returns>任务对象, 可以通过 Wait() 等待执行结束, 通过 Result 得到执行后的返回值</returns>
        public static Task<R> Run<R>(Func<R> function)
        {
            Task<R> task = new Task<R>(function);
            task.Start();
            return task;
        }

        /// <summary>
        /// 等待任意 Task 执行完成, 调用本函数将导致 调用线程阻塞, 直到任意任务完成, 并返回那个 最先执行完成的任务
        /// </summary>
        /// <param name="tasks">需要任意完成的任务</param>
        public static Task WhenAny(params Task[] tasks)
        {
            List<Task> list = tasks == null ? null : new List<Task>(tasks);
            return WhenAny(list);
        }
        /// <summary>
        /// 等待任意 Task 执行完成, 调用本函数将导致 调用线程阻塞, 直到任意任务完成, 并返回那个 最先执行完成的任务
        /// </summary>
        /// <param name="tasks">需要任意完成的任务</param>
        public static Task WhenAny(IList<Task> tasks)
        {
            if (tasks == null || tasks.Count <= 0) return null;

            System.Threading.ManualResetEvent resetEvent = new System.Threading.ManualResetEvent(false);
            resetEvent.Reset();
            Task task = null;

            int count = 0;
            foreach (Task tk in tasks)
            {
                if (tk == null) continue;
                else if (tk.IsCompleted) { resetEvent.Set(); task = tk; }
                else if (!tk.IsDisposed && !tk.IsCanceled && !tk.IsFaulted)
                {
                    tk.ContinueWith((t) => { resetEvent.Set(); task = tk; });
                    count++;
                }
            }

            if (count <= 0) resetEvent.Set();
            resetEvent.WaitOne();
            return task;
        }

        /// <summary>
        /// 等待所有 Task 全部执行完成, 调用本函数将导致 调用线程阻塞, 直到全部任务完成
        /// </summary>
        /// <param name="tasks">需要全部完成的任务</param>
        public static void WhenAll(params Task[] tasks)
        {
            List<Task> list = tasks == null ? null : new List<Task>(tasks);
            WhenAll(list);
        }
        /// <summary>
        /// 等待所有 Task 全部执行完成, 调用本函数将导致 调用线程阻塞, 直到全部任务完成
        /// </summary>
        /// <param name="tasks">需要全部完成的任务</param>
        public static void WhenAll(IList<Task> tasks)
        {
            if (tasks == null || tasks.Count <= 0) return;

            int count = 0;
            foreach (Task tk in tasks)
            {
                if (tk == null) continue;
                else if (tk.IsCompleted) continue;
                else if (!tk.IsDisposed && !tk.IsCanceled && !tk.IsFaulted) continue;
                tk.Wait();
                count++;
            }
        }

        /// <summary>
        /// 让当前线程休眠指定的时间差
        /// </summary>
        /// <param name="timeout">休眠的时间差</param>
        public static void Sleep(TimeSpan timeout)
        {
            System.Threading.Thread.Sleep(timeout);
        }
        /// <summary>
        /// 让当前线程休眠指定的毫秒数
        /// </summary>
        /// <param name="millisecondsTimeout">休眠的毫秒数</param>
        public static void Sleep(int millisecondsTimeout)
        {
            System.Threading.Thread.Sleep(millisecondsTimeout);
        }

        /// <summary>
        /// 阻塞当前线程, 开启一个自旋任务, 每隔20毫秒(默认时间间隔)的时间 就检查 func 是否满足条件, 满足条件就退出阻塞, 结束本函数的调用
        /// </summary>
        /// <param name="func">需要检查的满足条件</param>
        /// <returns>检查成功返回true, 超时也没有满足条件返沪false</returns>
        public static bool Tick(Func<bool> func)
        {
            return Tick(0, 20, func);
        }
        /// <summary>
        /// 阻塞当前线程, 开启一个自旋任务, 每隔20毫秒(默认时间间隔)的时间 就检查 func 是否满足条件, 满足条件就退出阻塞, 结束本函数的调用
        /// </summary>
        /// <param name="millisecondsTimeout">超时的毫秒数</param>
        /// <param name="func">需要检查的满足条件</param>
        /// <returns>检查成功返回true, 超时也没有满足条件返沪false</returns>
        public static bool Tick(int millisecondsTimeout, Func<bool> func)
        {
            return Tick(millisecondsTimeout, 20, func);
        }
        /// <summary>
        /// 阻塞当前线程, 开启一个自旋任务, 每隔一定的时间 就检查 func 是否满足条件, 满足条件就退出阻塞, 结束本函数的调用
        /// </summary>
        /// <param name="millisecondsTimeout">超时的毫秒数</param>
        /// <param name="interval">自旋判断的时间间隔毫秒数, 比如: 每10毫秒判断一次</param>
        /// <param name="func">需要检查的满足条件</param>
        /// <returns>检查成功返回true, 超时也没有满足条件返沪false</returns>
        public static bool Tick(int millisecondsTimeout, int interval, Func<bool> func)
        {
            if (func == null || func()) return true;

            DateTime endTime = DateTime.Now.AddMilliseconds(millisecondsTimeout);
            while (millisecondsTimeout <= 0 || endTime > DateTime.Now)
            {
                if (func()) return true;
                System.Threading.Thread.Sleep(interval);
            }
            return false;
        }



        /// <summary>
        /// 在指定的索引范围内, 开启一个多线程循环, 类似 for(int i=fromInclusive;i&lt;toExclusive;i++) { /*这个部分被多线程执行*/ }
        /// </summary>
        /// <param name="fromInclusive">其实索引</param>
        /// <param name="toExclusive">结束索引(不会取这个值)</param>
        /// <param name="action">执行体</param>
        /// <returns>已经执行结束的线程队列</returns>
        public static TaskQueue ForAndWait(int fromInclusive, int toExclusive, Action<int> action)
        {
            return ForAndWait(8, fromInclusive, toExclusive, action);
        }
        /// <summary>
        /// 在指定的索引范围内, 开启一个多线程循环, 类似 for(int i=fromInclusive;i&lt;toExclusive;i++) { /*这个部分被多线程执行*/ }
        /// </summary>
        /// <param name="threadCount">线程数</param>
        /// <param name="fromInclusive">其实索引</param>
        /// <param name="toExclusive">结束索引(不会取这个值)</param>
        /// <param name="action">执行体</param>
        /// <returns>已经执行结束的线程队列</returns>
        public static TaskQueue ForAndWait(int threadCount, int fromInclusive, int toExclusive, Action<int> action)
        {
            List<int> list = new List<int>();
            for (int i = fromInclusive; i < toExclusive; i++) list.Add(i);
            TaskQueue queue = For(threadCount, 0, list, action);
            queue.Wait();
            return queue;
        }


        /// <summary>
        /// 基于一个集合, 开启一个线程队列, 类似 foreach(object item in list) { /*这个部分被多线程执行*/ }
        /// </summary>
        /// <param name="list">需要执行循环的集合</param>
        /// <param name="action">执行体</param>
        /// <returns>未完成执行的线程队列, 如果需要等待完成, 需要调用 Wait() 函数</returns>
        public static TaskQueue For(IList list, Action<object> action)
        {
            return For(8, 0, list, action);
        }
        public static TaskQueue<T> For<T>(IList<T> list, Action<T> action)
        {
            return For(8, 0, list, action);
        }
        public static TaskQueueFunc<R> For<R>(IList list, Func<object, R> function)
        {
            return For(8, 0, list, function);
        }
        public static TaskQueueFunc<T, R> For<T, R>(IList<T> list, Func<T, R> function)
        {
            return For(8, 0, list, function);
        }

        /// <summary>
        /// 基于一个集合, 开启一个线程队列, 类似 foreach(object item in list) { /*这个部分被多线程执行*/ }
        /// </summary>
        /// <param name="threadCount">开启的线程数</param>
        /// <param name="retryCount">执行体执行异常时, 重试的次数</param>
        /// <param name="list">需要执行循环的集合</param>
        /// <param name="action">执行体</param>
        /// <returns>未完成执行的线程队列, 如果需要等待完成, 需要调用 Wait() 函数</returns>
        public static TaskQueue For(int threadCount, int retryCount, IList list, Action<object> action)
        {
            TaskQueue task = new TaskQueue(threadCount, retryCount, list, action);
            task.Start();
            return task;
        }
        public static TaskQueue<T> For<T>(int threadCount, int retryCount, IList<T> list, Action<T> action)
        {
            TaskQueue<T> task = new TaskQueue<T>(threadCount, retryCount, list, action);
            task.Start();
            return task;
        }
        public static TaskQueueFunc<R> For<R>(int threadCount, int retryCount, IList list, Func<object, R> function)
        {
            TaskQueueFunc<R> task = new TaskQueueFunc<R>(threadCount, retryCount, list, function);
            task.Start();
            return task;
        }
        public static TaskQueueFunc<T, R> For<T, R>(int threadCount, int retryCount, IList<T> list, Func<T, R> function)
        {
            TaskQueueFunc<T, R> task = new TaskQueueFunc<T, R>(threadCount, retryCount, list, function);
            task.Start();
            return task;
        }




        private static int m_TickId = 0;
        private static readonly object m_TickIdLocker = new object();
        private static int NewTaskId()
        {
            lock (m_TickIdLocker)
            {
                m_TickId = m_TickId + 1;
                return m_TickId;
            }
        }

        #endregion

        #region  仿 JS 时 钟 函 数

        /// <summary>
        /// 在延迟指定的毫秒数后, 执行指定的委托
        /// </summary>
        /// <param name="action">延迟执行的委托</param>
        /// <param name="milliseconds">延迟的毫秒数</param>
        /// <returns>定时器Id</returns>
        public static long SetTimeout(Action action, int milliseconds)
        {
            JSTimeAction info = JSTimeAction.Create(true, action, milliseconds);
            AppendJSTimeAction(info);
            return info.Id;
        }
        /// <summary>
        /// 在间隔指定的毫秒数后, 执行指定的委托
        /// </summary>
        /// <param name="action">延迟执行的委托</param>
        /// <param name="milliseconds">间隔的毫秒数</param>
        /// <returns>定时器Id</returns>
        public static long SetInterval(Action action, int milliseconds)
        {
            JSTimeAction info = JSTimeAction.Create(false, action, milliseconds);
            AppendJSTimeAction(info);
            return info.Id;
        }

        /// <summary>
        /// 删除指定Id的延迟委托
        /// </summary>
        /// <param name="timer">定时器Id</param>
        public static void ClearTimeout(long timer)
        {
            m_HashTimeFunc.Remove(timer);
        }
        /// <summary>
        /// 删除指定Id的定时委托
        /// </summary>
        /// <param name="timer">定时器Id</param>
        public static void ClearInterval(long timer)
        {
            m_HashTimeFunc.Remove(timer);
        }


        #region  JS 时 钟 核 心 逻 辑

        private class JSTimeAction : IDisposable
        {
            private static long m_TimeId = 0;
            private static readonly object m_TimeIdLocker = new object();
            public static long NewId()
            {
                lock (m_TimeIdLocker)
                {
                    m_TimeId = m_TimeId + 1;
                    return m_TimeId;
                }
            }



            public long Id;
            public bool Once;
            public int Interval;
            public Action Action;
            public Exception Error;
            public DateTime RunTime;

            public bool Invoke()
            {
                try
                {
                    Action();
                    if (Once)
                        return true;
                    else
                    {
                        RunTime = RunTime.AddMilliseconds(Interval);
                        return false;
                    }
                }
                catch (System.Threading.ThreadAbortException ex) { throw; }
                catch (Exception ex) { this.Error = ex; return false; }
            }
            public void Dispose()
            {
                Once = true;
                Interval = 0;
                Action = null;
                RunTime = DateTime.MinValue;
            }

            public static JSTimeAction Create(bool once, Action action, int interval)
            {
                JSTimeAction info = new JSTimeAction();
                info.Id = JSTimeAction.NewId();
                info.Once = once;
                info.Action = action;
                info.Interval = interval;
                info.RunTime = DateTime.Now.AddMilliseconds(interval);
                return info;
            }
        }


        #region  JS 时 钟 线 程

        private const int TIME_GCSIZE = 10000;
        private static bool m_TimeIsLocked = false;
        private static System.Threading.Thread m_TimeThread = null;
        private static readonly object m_TimeLocker1 = new object();
        private static readonly object m_TimeLocker2 = new object();
        private static readonly Hashtable m_HashTimeFunc = Hashtable.Synchronized(new Hashtable());
        private static System.Threading.ManualResetEvent m_TimeResetEvent = new System.Threading.ManualResetEvent(false);

        private static void AppendJSTimeAction(JSTimeAction action)
        {
            lock(m_HashTimeFunc.SyncRoot)
                m_HashTimeFunc[action.Id] = action;

            if (m_TimeIsLocked) return;
            StartJSTimeThread();
        }
        private static void StartJSTimeThread()
        {
            if (m_TimeIsLocked) return;
            m_TimeResetEvent.Set();
            if (m_TimeThread != null) return;
            if (m_HashTimeFunc.Count <= 0) return;
            bool result = System.Threading.Monitor.TryEnter(m_TimeLocker2);
            if (!result) return;

            try
            {
                m_TimeThread = new System.Threading.Thread(() =>
                {
                    try
                    {
                        Console.WriteLine("JS时钟线程启动...");
                        int idle = 0;
                        int count1 = 0;
                        while (m_HashTimeFunc.Count >= 1 || idle <= 200) //空闲50秒 线程退出
                        {
                            if (System.Threading.Thread.CurrentThread != m_TimeThread) return;
                            int count2 = RunJSTimeAction();
                            count1 = count1 + count2;
                            if (count1 > TIME_GCSIZE) { count1 = count1 - TIME_GCSIZE; GC.Collect(); } //每写入1W次Action, 回收一下内存
                            if (count2 > 0) idle = 0;
                            if (System.Threading.Thread.CurrentThread != m_TimeThread) return;
                            if (m_HashTimeFunc.Count <= 0) { m_TimeResetEvent.Reset(); m_TimeResetEvent.WaitOne(250); idle = idle + 1; }
                            else { System.Threading.Thread.Sleep(10); } //最小间隔10毫秒
                        }
                        m_TimeThread = null;
                        Console.WriteLine("JS时钟线程停止...");
                        GC.Collect();
                    }
                    catch (System.Threading.ThreadAbortException ex) { Console.WriteLine("JS时钟线程被手动终止(该错误无法被记录): \r\n " + ex); /*throw;*/ }
                    catch (Exception ex) { Console.WriteLine("JS时钟线程出现致命错误(该错误无法被记录): \r\n " + ex); }
                });
                m_TimeThread.Name = "JS_TIME";
                m_TimeThread.IsBackground = true;
                m_TimeThread.Start();
            }
            finally { System.Threading.Monitor.Exit(m_TimeLocker2); }
        }
        private static int RunJSTimeAction()
        {
            if (m_TimeIsLocked) return 0;
            bool result = System.Threading.Monitor.TryEnter(m_TimeLocker1);
            if (!result) return 0;

            try
            {
                m_TimeIsLocked = true;

                DateTime time = DateTime.Now;
                List<JSTimeAction> list = new List<JSTimeAction>();
                lock (m_HashTimeFunc.SyncRoot)
                {
                    foreach (object obj in m_HashTimeFunc.Values)
                    {
                        JSTimeAction action = obj as JSTimeAction;
                        if (action == null) continue;
                        if (action.Error == null && action.RunTime <= time) list.Add(action);
                    }
                }

                foreach (JSTimeAction action in list)
                {
                    bool delete = action.Invoke();
                    if (delete)
                    {
                        lock (m_HashTimeFunc.SyncRoot)
                            m_HashTimeFunc.Remove(action.Id);
                        action.Dispose();
                    }
                }
                list.Clear();
                return list.Count;
            }
            finally { m_TimeIsLocked = false; System.Threading.Monitor.Exit(m_TimeLocker1); }
        }


        #endregion



        #endregion

        #endregion






        #region  实 体 函 数

        public Task() { }
        public Task(Action action)
        {
            this.m_Action = action;
        }
        public Task(Action<Task> action, Task sender)
        {
            this.m_Action = () => { action(sender); };
        }


        private int m_Id = 0;
        protected TaskStatus m_Status = TaskStatus.Created;
        protected readonly object m_Locker = new object();
        protected System.Threading.ManualResetEvent m_ResetEvent = new System.Threading.ManualResetEvent(false);
        protected Action m_Action = null;
        protected Exception m_Exception = null;
        private System.Threading.Thread m_Thread = null;
        private List<Task> m_ListContinueTask = null;

        public int Id
        {
            get
            {
                if (m_Status == TaskStatus.Disposed) return 0;
                if (m_Id <= 0) m_Id = NewTaskId();
                return m_Id;
            }
        }
        public TaskStatus Status
        {
            get { return m_Status; }
        }
        public Exception Exception
        {
            get { return m_Exception; }
        }
        public bool IsCanceled
        {
            get { return m_Status == TaskStatus.Canceled; }
        }
        public bool IsCompleted
        {
            get { return m_Status == TaskStatus.Completed; }
        }
        public bool IsFaulted
        {
            get { return m_Status == TaskStatus.Faulted; }
        }
        public bool IsDisposed
        {
            get { return m_Status == TaskStatus.Disposed; }
        }



        public virtual void Start()
        {
            if (m_Status == TaskStatus.Disposed) return;
            if (m_Status != TaskStatus.Created) return;
            lock (m_Locker)
            {
                if (m_Status != TaskStatus.Created) return;
                m_ResetEvent.Reset();
                m_Status = TaskStatus.WaitingToRun;
                m_Thread = new System.Threading.Thread(ThreadWork);
                m_Thread.IsBackground = true;
                m_Thread.Name = string.Format("Task_{0}", this.Id);
                m_Thread.Start();
#if DEBUG
                Console.WriteLine(string.Format("任务启动 {0} (新线程执行单个任务)", m_Thread.Name));
#endif
            }
        }
        public virtual void Cancel()
        {
            if (m_Status == TaskStatus.Canceled) return;
            if (m_Status == TaskStatus.Completed || m_Status == TaskStatus.Faulted) { return; }  //这里可以抛出异常提示的
            if (m_Status == TaskStatus.Created || m_Status == TaskStatus.WaitingToRun) { m_Status = TaskStatus.Canceled; return; }

            try
            {
                if (m_Thread == null
                   || m_Thread.ThreadState == System.Threading.ThreadState.Stopped || m_Thread.ThreadState == System.Threading.ThreadState.StopRequested
                   || m_Thread.ThreadState == System.Threading.ThreadState.Aborted || m_Thread.ThreadState == System.Threading.ThreadState.AbortRequested
                   || m_Thread.ThreadState == System.Threading.ThreadState.Unstarted)
                    return;
                lock (m_Locker) m_Thread.Abort();
            }
            finally
            {
                lock (m_Locker) m_Status = TaskStatus.Canceled;
            }
        }
        public virtual bool Wait()
        {
            if (m_Status == TaskStatus.Disposed) return true;
            bool ok = m_ResetEvent.WaitOne();
            ThrowException();
            return ok;
        }
        public virtual bool Wait(TimeSpan timeout)
        {
            if (m_Status == TaskStatus.Disposed) return true;
            bool ok = m_ResetEvent.WaitOne(timeout);
            ThrowException();
            return ok;
        }
        public virtual bool Wait(int millisecondsTimeout)
        {
            if (m_Status == TaskStatus.Disposed) return true;
            bool ok = m_ResetEvent.WaitOne(millisecondsTimeout);
            ThrowException();
            return ok;
        }

        public Task ContinueWith(Action<Task> action)
        {
            if (m_Status == TaskStatus.Disposed) return null;

            Task parent = this;
            Task task = new Task(action, parent);
            this.AppendContinueTask(task);
            return task;
        }
        public Task<R> ContinueWith<R>(Func<Task, R> function)
        {
            if (m_Status == TaskStatus.Disposed) return null;

            Task parent = this;
            Task<R> task = new Task<R>(function, parent);
            this.AppendContinueTask(task);
            return task;
        }


        public virtual void SetStatus(TaskStatus status)
        {
            m_Status = status;
            if (status == TaskStatus.Canceled || status == TaskStatus.Completed || status == TaskStatus.Faulted || status == TaskStatus.Disposed)
                TaskFinished();
        }
        public virtual void SetException(Exception exception)
        {
            m_Exception = exception;
            TaskFinished();
        }


        private void ThreadWork(object state)
        {
            try
            {
                if (m_Status == TaskStatus.Canceled || m_Status == TaskStatus.Disposed) return;

                m_FinishRuned = false;
                this.m_Status = TaskStatus.Running;
                if (this.m_Action != null) this.m_Action();
                this.m_Status = TaskStatus.Completed;
            }
            catch (System.Threading.ThreadAbortException ex)
            {
#if DEBUG
                Console.WriteLine(string.Format("任务取消 {0} (单线程执行单个任务) -> {1}", System.Threading.Thread.CurrentThread.Name, ex.Message));
#endif
                if (m_Status != TaskStatus.Canceled)
                {
                    m_Exception = ex;
                    this.m_Status = TaskStatus.Faulted;
                }
            }
            catch (Exception ex)
            {
                m_Exception = ex;
                this.m_Status = TaskStatus.Faulted;
            }
            finally
            {
                TaskFinished();
            }
        }
        private void ThrowException()
        {
            if (m_Exception != null)
            {
                System.Threading.Thread.Sleep(10);
                throw new TaskException("发生一个或多个错误。", m_Exception);
            }
        }

        private bool m_FinishRuned = false;
        protected void TaskFinished()
        {
            try
            {
                if (m_FinishRuned) return;
                if (this.m_ResetEvent != null) this.m_ResetEvent.Set();
                StartContinueTask();
#if DEBUG
                Console.WriteLine(string.Format("任务退出 {0} (单线程执行单个任务) ", System.Threading.Thread.CurrentThread.Name));
#endif
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch { }
            finally { m_FinishRuned = true; m_Thread = null; }
        }
        protected void AppendContinueTask(Task task)
        {
            lock (m_Locker)
            {
                if (this.IsCanceled || this.IsCompleted || this.IsFaulted)
                    task.Start();
                else
                {
                    if (m_ListContinueTask == null)
                        m_ListContinueTask = new List<Task>();
                    m_ListContinueTask.Add(task);
                }
            }
        }
        protected void StartContinueTask()
        {
            lock (m_Locker)
            {
                if (m_ListContinueTask == null || m_ListContinueTask.Count <= 0) return;
                foreach (Task task in m_ListContinueTask)
                    task.Start();
                m_ListContinueTask.Clear();
                m_ListContinueTask = null;
            }
        }
        protected void DisposeContinueTask()
        {
            lock (m_Locker)
            {
                if (m_ListContinueTask == null || m_ListContinueTask.Count <= 0) return;
                foreach (Task task in m_ListContinueTask)
                    task.Start();
                m_ListContinueTask.Clear();
                m_ListContinueTask = null;
            }
        }


        public virtual void Dispose()
        {
            if (m_Status != TaskStatus.Completed && m_Status != TaskStatus.Faulted && m_Status != TaskStatus.Canceled)
                throw new TaskException("只有在任务处于完成状态时才能释放它。");

            this.m_Status = TaskStatus.Disposed;
            this.m_Id = 0;
            this.m_Action = null;
            this.m_Exception = null;
            if (this.m_ResetEvent != null) { this.m_ResetEvent.Set(); this.m_ResetEvent.Close(); }
            this.m_ResetEvent = null;
            DisposeContinueTask();
        }

        #endregion

    }
    internal class Task<R> : Task
    {
        public Task() : base() { }
        public Task(Func<R> function)
        {
            Task<R> task = this;
            this.m_Action = () => { task.m_Result = function(); };
        }
        public Task(Func<Task, R> function, Task sender)
        {
            Task<R> task = this;
            task.m_Action = () => { task.m_Result = function(sender); };
        }

        protected R m_Result = default(R);
        public R Result
        {
            get { return this.m_Result; }
        }


        public new R Wait()
        {
            base.Wait();
            return m_Result;
        }
        public new R Wait(TimeSpan timeout)
        {
            base.Wait(timeout);
            return m_Result;
        }
        public new R Wait(int millisecondsTimeout)
        {
            base.Wait(millisecondsTimeout);
            return m_Result;
        }

        public virtual void SetResult(R result)
        {
            m_Result = result;
            TaskFinished();
        }

        public override void Dispose()
        {
            base.Dispose();
            this.m_Result = default(R);
        }
    }
    internal class TaskCompletionSource<R> 
    {
        public TaskCompletionSource()
        {
            m_Task = new Task<R>();
            m_Task.SetStatus(TaskStatus.Created);
        }

        protected Task<R> m_Task = null;

        public Task<R> Task
        {
            get { return m_Task; }
        }


        public void Cancel()
        {
            m_Task.SetStatus(TaskStatus.Canceled);
        }
        public void SetResult(R result)
        {
            m_Task.SetResult(result);
            m_Task.SetStatus(TaskStatus.Completed);
        }
        public void SetException(Exception exception)
        {
            m_Task.SetException(exception);
            m_Task.SetStatus(TaskStatus.Faulted);
        }
        public void TrySetResult(R result)
        {
            SetResult(result);
        }
        public void TrySetException(Exception exception)
        {
            SetException(exception);
        }
    }



    internal class TaskQueue : Task
    {
        public TaskQueue()
        {
            this.m_RetryCount = 0;
            this.m_ThreadCount = 8;
        }
        public TaskQueue(IList list, Action<object> action)
        {
            this.m_RetryCount = 0;
            this.m_ThreadCount = 8;
            this.m_ListSource = list;
            this.m_ItemAction = action;
        }
        public TaskQueue(int thread, int retry, IList list, Action<object> action)
        {
            if (retry <= 0) retry = 0;
            if (thread <= 0) thread = 8;
            this.m_RetryCount = retry;
            this.m_ThreadCount = Math.Max(thread, 1);
            this.m_ListSource = list;
            this.m_ItemAction = action;
        }
        public static List<object> ToList(IList list)
        {
            List<object> list2 = new List<object>();
            if (list != null) foreach (object item in list) list2.Add(item);
            return list2;
        }
        public static List<T> ToList<T>(IList<T> list)
        {
            List<T> list2 = new List<T>();
            if (list != null) foreach (T item in list) list2.Add(item);
            return list2;
        }


        protected int m_ThreadCount;
        protected List<System.Threading.Thread> m_ListThread = null;
        protected int m_RetryCount;
        protected Action<object> m_ItemAction = null;
        protected IList m_ListSource;
        protected Hashtable m_HashItem;
        protected List<TaskItem> m_ListItemInit;
        protected List<TaskItem> m_ListItemRun;
        protected List<TaskItem> m_ListItemEnd;


        public override void Start()
        {
            if (m_Status == TaskStatus.Disposed) return;
            if (m_Status == TaskStatus.Running && m_Status != TaskStatus.WaitingToRun) return;
            lock (m_Locker)
            {
                if (m_Status == TaskStatus.Running && m_Status != TaskStatus.WaitingToRun) return;

#if DEBUG
                Console.WriteLine(string.Format("任务组启动 Task_{0} (以多线程合力完成多个任务)", this.Id));
#endif
                m_ResetEvent.Reset();
                m_Status = TaskStatus.WaitingToRun;

                if (m_ListSource == null || m_ListSource.Count <= 0)
                    EndTaskAction();
                else
                {
                    InitTaskItem();
                    RunItemThread();
                }
            }
        }
        //public override void Wait()
        //{
        //    base.Wait();
        //}
        //public override void Wait(TimeSpan timeout)
        //{
        //    base.Wait(timeout);
        //}
        //public override void Wait(int millisecondsTimeout)
        //{
        //    base.Wait(millisecondsTimeout);
        //}
        public virtual void Add(object item)
        {
            if (m_Status == TaskStatus.Disposed) return;
            lock (m_Locker)
            {
                if (m_ListItemInit == null) InitTaskItem();
                if (m_ListItemInit == null) m_ListItemInit = new List<TaskItem>(); //不可达代码
                if (item == null) return;

                TaskItem temp = new TaskItem(item);
                m_ListSource.Add(item);
                m_HashItem[item] = temp;
                m_ListItemInit.Add(temp);

                bool calledStart = m_Status != TaskStatus.Created;
                bool threadNull = (m_ListThread == null || m_ListThread.Count <= 0);
                if (calledStart && threadNull) this.Start();
            }
        }
        public virtual void Add(IList list)
        {
            if (m_Status == TaskStatus.Disposed) return;
            lock (m_Locker)
            {
                if (m_ListItemInit == null) InitTaskItem();
                if (m_ListItemInit == null) m_ListItemInit = new List<TaskItem>(); //不可达代码

                foreach (object item in list)
                {
                    if (item == null) continue;
                    TaskItem temp = new TaskItem(item);
                    m_ListSource.Add(item);
                    m_HashItem[item] = temp;
                    m_ListItemInit.Add(temp);
                }

                bool calledStart = m_Status != TaskStatus.Created;
                bool threadNull = (m_ListThread == null || m_ListThread.Count <= 0);
                if (calledStart && threadNull) this.Start();
            }
        }
        public virtual void Clear()
        {
            if (m_Status == TaskStatus.Disposed) return;
            lock (m_Locker)
            {
                if (m_ListSource != null) m_ListSource.Clear();
                if (m_HashItem != null) m_HashItem.Clear();
                if (m_ListItemInit != null) m_ListItemInit.Clear();
                if (m_ListItemRun != null) m_ListItemRun.Clear();
                if (m_ListItemEnd != null) m_ListItemEnd.Clear();
            }
        }
        public override void Cancel()
        {
            Task.Run(() =>
            {
                if (m_Status == TaskStatus.Canceled) return;
                if (m_Status == TaskStatus.Completed || m_Status == TaskStatus.Faulted) { return; }  //这里可以抛出异常提示的
                if (m_Status == TaskStatus.Created || m_Status == TaskStatus.WaitingToRun) { m_Status = TaskStatus.Canceled; return; }

                lock (m_Locker)
                {
                    m_Status = TaskStatus.Canceled;
                    #region  终止所有线程

                    if (m_ListThread != null)
                    {
                        foreach (System.Threading.Thread thread in m_ListThread)
                        {
                            if (thread == null
                            || thread.ThreadState == System.Threading.ThreadState.Stopped || thread.ThreadState == System.Threading.ThreadState.StopRequested
                            || thread.ThreadState == System.Threading.ThreadState.Aborted || thread.ThreadState == System.Threading.ThreadState.AbortRequested
                            || thread.ThreadState == System.Threading.ThreadState.Unstarted)
                                continue;

                            thread.Abort();
                        }
                    }

                    #endregion

                    #region  将所有未完成任务标记为Canceled, 并且移动到 完成集合

                    if (m_ListItemEnd == null) m_ListItemEnd = new List<TaskItem>();

                    if (m_ListItemInit != null && m_ListItemInit.Count >= 0)
                    {
                        foreach (TaskItem item in m_ListItemInit) { if (item != null) item.Cancel(); }
                        m_ListItemEnd.AddRange(m_ListItemInit);
                        m_ListItemInit.Clear();
                    }

                    if (m_ListItemRun != null && m_ListItemRun.Count >= 0)
                    {
                        foreach (TaskItem item in m_ListItemRun) { if (item != null) item.Cancel(); }
                        m_ListItemEnd.AddRange(m_ListItemRun);
                        m_ListItemRun.Clear();
                    }

                    #endregion
                }

                System.Threading.Thread.Sleep(100);
                if (this.m_ResetEvent != null) this.m_ResetEvent.Set();
            });
        }


        protected void EndTaskAction()
        {
#if DEBUG
            Console.WriteLine(string.Format("任务组退出 Task_{0} (以多线程合力完成多个任务)", this.Id));
#endif
            m_Status = TaskStatus.Completed;
            if (this.m_ResetEvent != null) m_ResetEvent.Set();
            StartContinueTask();
        }


        protected void RunItemThread()
        {
            if (m_Status == TaskStatus.Disposed) return;
            if (m_ListItemInit == null || m_ListItemInit.Count <= 0) return;
            if (m_ListThread != null && (m_ListThread.Count >= m_ListItemInit.Count || m_ListThread.Count >= m_ThreadCount)) return;

            lock (m_Locker)
            {
                if (m_ListThread == null) m_ListThread = new List<System.Threading.Thread>();
                int diff = Math.Min(m_ThreadCount, m_ListItemInit.Count) - m_ListThread.Count;
                if (diff <= 0) return;

                for (int i = 0; i < diff; i++)
                {
                    System.Threading.Thread thread = new System.Threading.Thread(ThreadItemWork);
                    thread.Name = string.Format("Task_{0}_{1}", this.Id, (m_ListThread.Count + 1));
                    thread.IsBackground = true;
                    m_ListThread.Add(thread);
#if DEBUG
                    Console.WriteLine(string.Format("线程启动 {0}", thread.Name));
#endif
                    thread.Start();
                }
            }
        }
        protected void EndItemThread(Exception error)
        {
#if DEBUG
            Console.WriteLine(string.Format("线程退出 {0}", System.Threading.Thread.CurrentThread.Name));
#endif
            lock (m_Locker)
            {
                if (error != null)
                {
                    TaskMultiException multiException = m_Exception as TaskMultiException;
                    if (multiException == null) m_Exception = multiException = new TaskMultiException();
                    multiException.AppendTaskException(new TaskException(string.Format("成员线程 \"{0}\" 发生错误", System.Threading.Thread.CurrentThread.Name), error));
                }

                System.Threading.Thread thread = System.Threading.Thread.CurrentThread;
                m_ListThread.Remove(thread);

                int initCount = m_ListItemInit == null ? 0 : m_ListItemInit.Count;
                int runCount = m_ListItemRun == null ? 0 : m_ListItemRun.Count;
                int endCount = m_ListItemEnd == null ? 0 : m_ListItemEnd.Count;

                if (initCount <= 0 && runCount <= 0 && m_ListThread.Count <= 0) EndTaskAction();
            }
        }

        protected void InitTaskItem()
        {
            lock (m_Locker)
            {
                #region  初始化数据

                if (m_HashItem == null) m_HashItem = Hashtable.Synchronized(new Hashtable());
                if (m_ListItemInit == null) m_ListItemInit = new List<TaskItem>();
                if (m_ListItemRun == null) m_ListItemRun = new List<TaskItem>();
                if (m_ListItemEnd == null) m_ListItemEnd = new List<TaskItem>();

                if (m_ListItemInit.Count <= 0 && m_ListItemRun.Count <= 0 && m_ListItemEnd.Count <= 0)
                {
                    foreach (object temp in m_ListSource)
                    {
                        if (m_HashItem.ContainsKey(temp)) continue;

                        TaskItem item = new TaskItem(temp);
                        m_HashItem[temp] = item;
                        m_ListItemInit.Add(item);
                    }
                }

                #endregion
            }
        }
        protected TaskItem ApplyTaskItem()
        {
            if (m_ListItemInit == null || m_ListItemInit.Count <= 0) return null;

            lock (m_Locker)
            {
                if (m_ListItemInit.Count >= 1)
                {
                    TaskItem item = m_ListItemInit[0];
                    m_ListItemInit.RemoveAt(0);
                    m_ListItemRun.Add(item);
                    return item;
                }
            }

            return null;
        }
        protected void EndTaskItem(TaskItem item)
        {
            if (item == null) return;
            lock (m_Locker)
            {
                m_ListItemRun.Remove(item);
                m_ListItemEnd.Add(item);
            }
        }

        protected void AppendResult(object item, object result)
        {
            if (m_HashItem == null) return;
            TaskItem actionItem = m_HashItem[item] as TaskItem;
            if (actionItem == null) return;
            actionItem.SetResult(result);
        }

        protected List<TaskResult> ToListResult()
        {
            lock (m_Locker)
            {
                if (m_ListSource == null) return null;
                List<TaskResult> list = new List<TaskResult>();
                foreach (object temp in m_ListSource)
                {
                    TaskItem item = m_HashItem[temp] as TaskItem;
                    TaskResult result = new TaskResult(item);
                    list.Add(result);
                }
                return list;
            }
        }
        protected List<TaskResult<R>> ToListResult<R>()
        {
            lock (m_Locker)
            {
                if (m_ListSource == null) return null;
                List<TaskResult<R>> list = new List<TaskResult<R>>();
                foreach (object temp in m_ListSource)
                {
                    TaskItem item = m_HashItem[temp] as TaskItem;
                    TaskResult<R> result = new TaskResult<R>(item);
                    list.Add(result);
                }
                return list;
            }
        }


        protected void ThreadItemWork(object state)
        {
            //以下代码虽然凌乱, 尤其是 EndItemThread(*) 函数的调用 没有放到 finally 中
            //这些都是有意为之: 因为 EndItemThread(*) 函数在正常结束时, 必须被 lock(m_Locker) 包围起来 
            //—— 一切都是为了多线程的稳定

            try
            {
                if (m_Status == TaskStatus.Disposed) return;
                if (m_Status == TaskStatus.Canceled) return;
                if (m_Status == TaskStatus.WaitingToRun) m_Status = TaskStatus.Running;
                do
                {
                    TaskItem item = null;
                    lock (m_Locker)
                    {
                        item = ApplyTaskItem();
                        if (item == null) { EndItemThread(null); return; }
                    }
                    item.Proc(this.m_RetryCount, this.m_ItemAction);
                    EndTaskItem(item);
                } while (m_Status != TaskStatus.Canceled && m_Status != TaskStatus.Disposed);
            }
            catch (System.Threading.ThreadAbortException ex) 
            {
                if (m_Status == TaskStatus.Canceled) { EndItemThread(null); }
                else EndItemThread(ex); 
            }
            catch (Exception ex) { EndItemThread(ex); }
        }

        public class TaskItem
        {
            public TaskItem(object item)
            {
                this.m_Item = item;
                this.m_Status = TaskItemStatus.Created;
            }

            private int m_Retry = 0;
            private object m_Item = null;
            private object m_Result = null;
            private Exception m_Exception = null;
            private TaskItemStatus m_Status;
            private System.Threading.Thread m_Thread;
            protected readonly object m_Locker = new object();

            public int Retry
            {
                get { return m_Retry; }
            }
            public object Item
            {
                get { return m_Item; }
            }
            public object Result
            {
                get { return m_Result; }
            }
            public Exception Exception
            {
                get { return m_Exception; }
            }
            public TaskItemStatus Status
            {
                get { return m_Status; }
            }


            public void Cancel()
            {
                lock (m_Locker)
                {
                    m_Thread = null;
                    m_Status = TaskItemStatus.Canceled;
                }
            }
            public void SetResult(object result)
            {
                lock (m_Locker) { m_Result = result; }
            }
            public void Proc(int retry, Action<object> action)
            {
                lock (m_Locker)
                {
                    System.Threading.Thread thread = System.Threading.Thread.CurrentThread;
                    if (m_Thread != null && m_Thread != thread)
                    {
                        //throw new TaskException("任务数据正在被其他线程处理。");
                        return;
                    }    
                }

                if (retry < 0) retry = 0;
                Exception error = null;
                m_Status = TaskItemStatus.WaitingToRun;
                for (int i = 0; i <= retry; i++) //重试
                {
                    try
                    {
                        error = null;
                        m_Status = i == 0 ? TaskItemStatus.Running : TaskItemStatus.RetryRunning;
                        if (action != null) action(this.Item);
                        m_Status = TaskItemStatus.Completed;
                        break;
                    }
                    catch (System.Threading.ThreadAbortException) { throw; }
                    catch (Exception ex) { error = ex; }
                }
                if (error != null)
                {
                    m_Status = TaskItemStatus.Faulted;
                    m_Exception = error;
                }
            }
        }

    }
    internal class TaskQueue<T> : TaskQueue
    {
        public TaskQueue() : base() { }
        public TaskQueue(IList<T> list, Action<T> action) : this()
        {
            this.m_ListSource = TaskQueue.ToList(list);
            this.m_ItemAction = (item) => { action((T)item); };
        }
        public TaskQueue(int thread, int retry, IList<T> list, Action<T> action)
        {
            if (retry <= 0) retry = 0;
            if (thread <= 0) thread = 8;
            this.m_RetryCount = retry;
            this.m_ThreadCount = Math.Max(thread, 1);
            this.m_ListSource = TaskQueue.ToList(list);
            this.m_ItemAction = (item) => { action((T)item); };
        }
    }
    internal class TaskQueueFunc<R> : TaskQueue
    {
        public TaskQueueFunc() : base() { }
        public TaskQueueFunc(IList list, Func<object, R> function) : this()
        {
            TaskQueueFunc<R> task = this;
            this.m_ListSource = TaskQueue.ToList(list);
            this.m_ItemAction = (item) => { R result = function(item); task.AppendResult(item, result); };
        }
        public TaskQueueFunc(int thread, int retry, IList list, Func<object, R> function)
        {
            if (retry <= 0) retry = 0;
            if (thread <= 0) thread = 8;
            TaskQueueFunc<R> task = this;
            this.m_RetryCount = retry;
            this.m_ThreadCount = Math.Max(thread, 1);
            this.m_ListSource = TaskQueue.ToList(list);
            this.m_ItemAction = (item) => { R result = function(item); task.AppendResult(item, result); };
        }

        public new List<TaskResult> Wait()
        {
            base.Wait();
            return this.ToListResult();
        }
        public new List<TaskResult> Wait(TimeSpan timeout)
        {
            base.Wait(timeout);
            return this.ToListResult();
        }
        public new List<TaskResult> Wait(int millisecondsTimeout)
        {
            base.Wait(millisecondsTimeout);
            return this.ToListResult();
        }

    }
    internal class TaskQueueFunc<T, R> : TaskQueueFunc<R>
    {
        public TaskQueueFunc() : base() { }
        public TaskQueueFunc(IList<T> list, Func<T, R> function) : this()
        {
            TaskQueueFunc<T, R> task = this;
            this.m_ListSource = TaskQueue.ToList(list);
            this.m_ItemAction = (item) => { R result = function((T)item); task.AppendResult(item, result); };
        }
        public TaskQueueFunc(int thread, int retry, IList<T> list, Func<T, R> function)
        {
            if (retry <= 0) retry = 0;
            if (thread <= 0) thread = 8;
            TaskQueueFunc<T, R> task = this;
            this.m_RetryCount = retry;
            this.m_ThreadCount = Math.Max(thread, 1);
            this.m_ListSource = TaskQueue.ToList(list);
            this.m_ItemAction = (item) => { R result = function((T)item); task.AppendResult(item, result); };
        }
    }








    [Serializable]
    internal class TaskResult
    {
        public TaskResult() { }
        public TaskResult(TaskQueue.TaskItem item)
        {
            if (item != null)
            {
                m_Item = item.Item;
                m_Result = item.Result;
                m_Exception = item.Exception;
                m_Status = item.Status;
            }
        }

        protected object m_Item = null;
        protected object m_Result = null;
        protected Exception m_Exception = null;
        protected TaskItemStatus m_Status = TaskItemStatus.Created;

        public object Item
        {
            get { return m_Item; }
        }
        public object Result
        {
            get { return m_Result; }
        }
        public Exception Exception
        {
            get { return m_Exception; }
        }
        public TaskItemStatus Status
        {
            get { return m_Status; }
        }

        public override string ToString()
        {
            return string.Format("{0,-16} {1} >>> {2}", "[" + this.Status + "]", this.Item, this.Result);
        }
    }
    [Serializable]
    internal class TaskResult<R> : TaskResult
    {
        public TaskResult() { }
        public TaskResult(TaskQueue.TaskItem item)
        {
            if (item != null)
            {
                m_Item = item.Item;
                m_Result = (R)item.Result;
                m_Exception = item.Exception;
                m_Status = item.Status;
            }
        }

        public new R Result
        {
            get { return (R)m_Result; }
        }
    }



    [Serializable]
    internal enum TaskStatus
    {
        Created,
        WaitingToRun,
        Running,
        Completed,
        Canceled,
        Faulted,
        Disposed,
    }
    [Serializable]
    internal enum TaskItemStatus
    {
        Created,
        WaitingToRun,
        Running,
        RetryRunning,
        Completed,
        Canceled,
        Faulted,
        Disposed,
    }
    [Serializable]
    internal class TaskException : Exception
    {
        public TaskException() : base() { }
        public TaskException(string message) : base(message) { }
        public TaskException(string message, Exception innerException) : base(message, innerException) { }
        public TaskException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
    }
    [Serializable]
    internal class TaskMultiException : TaskException
    {
        public TaskMultiException() : base(MESSAGE) { }
        public TaskMultiException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }


        private const string MESSAGE = @"发生多个任务线程异常"; 
        private List<TaskException> m_ListException;
        private readonly object m_Locker = new object();

        public List<TaskException> ListException
        {
            get
            {
                if (m_ListException == null) m_ListException = new List<TaskException>();
                return m_ListException;
            }
        }

        public void AppendTaskException(TaskException error)
        {
            if (error == null) return;
            lock (m_Locker)
            {
                if (m_ListException == null) m_ListException = new List<TaskException>();
                m_ListException.Add(error);
            }
        }
        public override string ToString()
        {
            const string LINE = @"----------------------------------";

            string baseStr = base.ToString();
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(baseStr);
            sb.Append(LINE);
            if (m_ListException != null && m_ListException.Count >= 1)
            {
                foreach (TaskException error in m_ListException)
                {
                    if (error == null) continue;
                    sb.AppendLine(error.ToString());
                    sb.Append(LINE);
                }
            }
            return sb.ToString();
        }
    }
}


